#region Microsoft Public License
/*
 * (c) Copyright Chenjun Wu. http://utablesdk.codeplex.com
 * 
 * This source is subject to the Microsoft Public License (Ms-PL).
 * Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
 * All other rights reserved.
 */
#endregion

﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UTable.Input.MultiTouch;
using System.Windows.Threading;
using UTable.Objects.Controls;
using System.Windows;

namespace UTable.Objects.Handlers
{
    public class FingersHoldHandler: MultiTouchEventHandlerClass
    {
        private int holdRadius = 10;    // pixels
        private int holdTime = 2000;   // Milliseconds
		private bool routeDown = true;
		private Dictionary<int, DispatcherTimer> _holdFingersList = new Dictionary<int, DispatcherTimer>();
        private Dictionary<int, Point> _holdFingerPositionList = new Dictionary<int, Point>();
		private Dictionary<int, Point> _holdFingerLocalPositionList = new Dictionary<int, Point>();
        private Dictionary<UElementMenu, int> _menuList = new Dictionary<UElementMenu, int>();
        private Dictionary<UElementMenu, Point> _menuPositionList = new Dictionary<UElementMenu, Point>();

		public IVisualNode Owner { get;set; }

        public int HoldRadius
        {
            get { return holdRadius; }
            set { holdRadius = value; }
        }

        public int HoldTime
        {
            get { return holdTime; }
            set { holdTime = value; }
        }

		public bool RouteEventDown
		{
			get { return routeDown; }
			set { routeDown = value; }
		}

        public override void OnMultiTouch(MultiTouchEventArgs args)
        {
            foreach (FingerEventArgs f in args.FingerEvents)
            {
                Console.WriteLine(f.EventType);
                switch (f.EventType)
                {
                    case FingerEventType.FINGER_DOWN_EVENT:
                        Console.WriteLine("Add {0}", f.FingerID);
                        DispatcherTimer startTimer = new DispatcherTimer();
                        startTimer.Tick += new EventHandler(startTimer_Elapsed);
                        startTimer.Interval = TimeSpan.FromMilliseconds(holdTime);
                        _holdFingersList.Add(f.FingerID, startTimer);
                        _holdFingerPositionList.Add(f.FingerID, f.GlobalPosition);
						_holdFingerLocalPositionList.Add(f.FingerID, f.Position);
                        startTimer.Start();
                        break;
                    case FingerEventType.FINGER_UP_EVENT:
                    case FingerEventType.FINGER_OUT_EVENT:
                        Console.WriteLine("Check contain {0}", f.FingerID);
                        if (_holdFingersList.ContainsKey(f.FingerID))
                        {
                            Console.WriteLine("Remove {0}", f.FingerID);
                            DispatcherTimer timer = _holdFingersList[f.FingerID];
                            timer.Stop();
                            _holdFingersList.Remove(f.FingerID);
                            _holdFingerPositionList.Remove(f.FingerID);
							_holdFingerLocalPositionList.Remove(f.FingerID);
                        }
                        break;
                    case FingerEventType.FINGER_MOVE_EVENT:
                        if (_holdFingersList.ContainsKey(f.FingerID))
                        {
                            double distance = (f.GlobalPosition - _holdFingerPositionList[f.FingerID]).Length;
                            if (distance > holdRadius)
                            {
                                _holdFingersList.Remove(f.FingerID);
                                _holdFingerPositionList.Remove(f.FingerID);
								_holdFingerLocalPositionList.Remove(f.FingerID);
                            }
                        }
                        break;
                }
            }
        }

        void startTimer_Elapsed(object sender, EventArgs e)
        {
            DispatcherTimer timer = sender as DispatcherTimer;
            timer.Stop();
            if (_holdFingersList.ContainsValue(timer))
            {
                // invoke the event
                int finger = 0;
                foreach (int f in _holdFingersList.Keys)
                {
                    if (_holdFingersList[f] == timer)
                    {
                        finger = f;
                        break;
                    }
                }

                if (FingerHolded != null)
                {
					FingerHolded(this, new FingersHoldEventArgs(finger, _holdFingerLocalPositionList[finger]));
                }

                _holdFingersList.Remove(finger);
                _holdFingerPositionList.Remove(finger);
				_holdFingerLocalPositionList.Remove(finger);
            }
        }

        public event FingersHoldEventHandler FingerHolded;
    }

    public class FingersHoldEventArgs
    {
        public FingersHoldEventArgs(int fingerID, Point position)
        {
            FingerID = fingerID;
            Position = position;
        }

        public int FingerID { get; protected set; }

        public Point Position { get; protected set; }
    }

    public delegate void FingersHoldEventHandler(FingersHoldHandler sender, FingersHoldEventArgs args);
}
